﻿using System;
using StockAccessors;
using StockAnalyst2.Chart;
using StockAnalyst2.Plugins.Engine;
using StockEngine.Historical;
using StockEngine.RealTime;
using StockModel;
using Utils;
using Utils.Extensions;
using StockAnalyst2.Plugins.Visualization.Realtime;

namespace StockAnalyst2
{
	internal class ApplicationInitializer : IDisposable
	{
		#region Attributes

		private IDataBaseClient _dbClient;
		
		#endregion

		#region Properties

		public PluginSystem PluginSystem { get; private set; }
		public StockGroupDataSource StockGroupDataSource { get; private set; }
		public QuotationDataSource QuotationDataSource { get; private set; }
		public ExchangeMarketDataSource ExchangeMarketDataSource { get; private set; }
		public RawStockDataSource RawStockDataSource { get; private set; }
		public IStockDataAccessor Accessor { get; private set; }
		public IOrderExecutor OrderExecutor { get; private set; }
		public AcquisitionSystem RealTimeSystem { get; private set; }
		public HistoricalSystem HistoricalSystem { get; private set; }
		public NotificationDataSource NotificationDataSource { get; private set; }
		public Generator ChartGenerator { get; private set; }

		#endregion

		#region Public Methos

		public ApplicationInitializer()
		{
			this.PluginSystem = new PluginSystem();
		}

		public void Initialize()
		{
			AccessorFactory accessorFactory = new AccessorFactory(Properties.Settings.Default.UserName, Properties.Settings.Default.Password.Decrypt());

			_dbClient = new SqlDataBaseClient(string.Format(Properties.Settings.Default.ConnectionString, Properties.Settings.Default.DatabaseServer, Properties.Settings.Default.DatabaseName));

			this.ChartGenerator = new Generator();

			this.ExchangeMarketDataSource = new ExchangeMarketDataSource(_dbClient);
			this.StockGroupDataSource = new StockGroupDataSource(this.ExchangeMarketDataSource, _dbClient);
			this.QuotationDataSource = new QuotationDataSource(_dbClient);
			this.NotificationDataSource = new NotificationDataSource(_dbClient);
			this.RawStockDataSource = new RawStockDataSource(_dbClient, this.ExchangeMarketDataSource);

			this.Accessor = accessorFactory.CreateAccessor();
			this.OrderExecutor = accessorFactory.CreateOrderExecutor();
			this.OrderExecutor.IsSimulationEnabled = Properties.Settings.Default.EnableOrderSimulation;

			this.RealTimeSystem = new AcquisitionSystem(this.ExchangeMarketDataSource, this.StockGroupDataSource, this.QuotationDataSource, this.Accessor, Properties.Settings.Default.EnableParallel);
			this.HistoricalSystem = new HistoricalSystem(this.StockGroupDataSource, this.QuotationDataSource, Properties.Settings.Default.EnableParallel);

			this.PluginSystem.Initialize(_dbClient, this.QuotationDataSource, this.ExchangeMarketDataSource, this.RawStockDataSource, this.RealTimeSystem.Groups, this.OrderExecutor, this.Accessor.Information);
		}

		#endregion

				#region IDisposable

		protected bool Disposed { get; private set; }

		private void Dispose(bool disposing)
		{
			if (!this.Disposed)
			{
				this.InternalDispose(disposing);
			}

			this.Disposed = true;
		}

		protected virtual void InternalDispose(bool disposing)
		{
			if (disposing)
			{
				if (_dbClient is IDisposable)
				{
					((IDisposable)_dbClient).Dispose();
				}
			}

			// Dispose here only unmanaged objects 
			// Don’t use managed objects here because maybe 
			// they have been finalized already
		}

		public void Dispose()
		{
			this.Dispose(true);
			GC.SuppressFinalize(this);
		}

		~ApplicationInitializer()
		{
			this.Dispose(false);
		}

		#endregion

	}
}
